﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.ServiceProcess;
using EnOcean;
using EnOcean.Radio.Sensor;
using EnOceanReceiver;
using EnOceanTransmitter;
using OutdoorLight.Properties;

namespace OutdoorLight
{
  public partial class OutdoorLightService : ServiceBase
  {
    private Receiver receiver;
    private Transmitter transmitter;
    private bool requiredTransmitterAvailable;
    private RepeatedSwitchNTelegram on;
    private RepeatedSwitchNTelegram off;

    public OutdoorLightService()
    {
      InitializeComponent();
    }

    protected override void OnStart(string[] args)
    {
      List<long> sensors;

      sensors = new List<long>();
      sensors.Add(0x142F6);

      requiredTransmitterAvailable = false;
      

      on = new RepeatedSwitchNTelegram()
      {
        IsEnergyBowPressed = true,
        FirstButtonId = 0,
        FirstButtonState = ButtonState.I,
        HasSecondAction = false,
        SwitchType = SwitchType.Type2,
        Id = 0xFFCC6D03
      };

      off = new RepeatedSwitchNTelegram()
      {
        IsEnergyBowPressed = true,
        FirstButtonId = 0,
        FirstButtonState = ButtonState.O,
        HasSecondAction = false,
        SwitchType = SwitchType.Type2,
        Id = 0xFFCC6D03
      };

      try
      {
        receiver = new Receiver(sensors);
        receiver.TelegramReceived += new EventHandler<TelegramReceivedEventArgs>(TelegramReceived);
        receiver.Start();

        transmitter = new Transmitter();
        transmitter.TransmitterAvailable += new EventHandler(TransmitterAvailabillityChanged);
        transmitter.TransmitterUnavailable += new EventHandler(TransmitterAvailabillityChanged);
        transmitter.UnhandledException += new EventHandler<UnhandledExceptionEventArgs>(TransmitterUnhandledException);
        transmitter.Start();
      }
      catch (Exception e)
      {
        EventLog.WriteEntry(e.ToString(), EventLogEntryType.Error);
      }
    }

    protected override void OnStop()
    {
      try
      {
        receiver.Stop();
        transmitter.Stop();
      }
      catch (Exception e)
      {
        EventLog.WriteEntry(e.ToString(), EventLogEntryType.Error);
      }
    }

    private void TransmitterUnhandledException(object sender, UnhandledExceptionEventArgs e)
    {
      EventLog.WriteEntry(e.ExceptionObject.ToString(), EventLogEntryType.Error);
    }

    private void TransmitterAvailabillityChanged(object sender, EventArgs e)
    {
      try
      {
        if (transmitter.GetAvailableBaseIds().Contains(0xFFCC6D00))
        {
          requiredTransmitterAvailable = true;
          EventLog.WriteEntry("TransmitterAvailable", EventLogEntryType.Information);
        }
        else
        {
          requiredTransmitterAvailable = false;
          EventLog.WriteEntry("TransmitterUnavailable", EventLogEntryType.Information);
        }
      }
      catch (Exception ex)
      {
        EventLog.WriteEntry(ex.ToString(), EventLogEntryType.Error);
      }
    }

    private void TelegramReceived(object sender, TelegramReceivedEventArgs e)
    {
      FourByteSensorDataTelegram t;
      decimal brightness;

      try
      {
        if (requiredTransmitterAvailable)
        {
          if (e.Telegram is FourByteSensorDataTelegram)
          {
            t = (FourByteSensorDataTelegram)e.Telegram;

            brightness = Telegram.ConvertRange(t.Data2, 0, 255, 300, 30000);

            if (DateTime.Now.TimeOfDay >= Settings.Default.BlackOutPeriodStart && DateTime.Now.TimeOfDay < Settings.Default.BlackOutPeriodEnd)
            {
              SwitchLightOff();
            }
            else
            {
              if (brightness <= Settings.Default.OnThreshold)
              {
                SwitchLightOn();
              }
              else if (brightness >= Settings.Default.OffThreshold)
              {
                SwitchLightOff();
              }
            }
          }
        }
      }
      catch (Exception ex)
      {
        EventLog.WriteEntry(ex.ToString(), EventLogEntryType.Error);
      }
    }

    private void SwitchLightOn() {
      transmitter.Send(on);
    }

    private void SwitchLightOff()
    {
      transmitter.Send(off);
    }


  }
}
